
#include "testBullet.h"

#include <BulletCollision/CollisionDispatch/btSphereSphereCollisionAlgorithm.h>
#include <BulletCollision/NarrowPhaseCollision/btGjkEpa2.h>
#include "LinearMath/btQuickprof.h"
#include "LinearMath/btIDebugDraw.h"

#include <BulletSoftBody/btSoftBodyRigidBodyCollisionConfiguration.h>
#include <BulletSoftBody/btSoftBodyHelpers.h>
#include <mmsystem.h>

//-------------------------------------------------------------------------------------
testBullet::testBullet(void):
mWorld(NULL), mMovV(150),mNewSphere(NULL),m_VehicleRotateState(0),
m_StartPhy(false),m_LMouseDown(false),m_RMouseDown(false),m_ViewState(CAMERA_WORLD_VIEW), 
m_AltKeyPressed(false), m_ObjMovState(0), m_UseRB(false), m_UseNV(false), m_BoatShoot(false)
{
}
//-------------------------------------------------------------------------------------
testBullet::~testBullet(void)
{
}

//-------------------------------------------------------------------------------------
void testBullet::createScene(void)
{
	//Scene setup
	Ogre::Light *light = mSceneMgr->createLight( "light0" );
	light->setType( Ogre::Light::LT_DIRECTIONAL );
	light->setDirection( Ogre::Vector3( 0, -1, 0 ) );
	light->setPosition(750.0, 1000.0, 750.0);
	light->setCastShadows(true);

	//mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f));
	mTrayMgr->showCursor();
	//camera setup
// 	mCamera->setPosition(0, 200, 100);
// 	mCamera->lookAt(0,0,0);
	
	
	m_ObjCtrl = new ObjectControl(mSceneMgr, mCamera);
	m_ObjCtrl->init();
	m_ObjCtrl->AddMavableFlag(0x1);
	mCameraMan->setStyle(OgreBites::CameraStyle::CS_MANUAL);

	m_SkyMgr = NULL;
	m_SkyMgr = new SkyManager(mSceneMgr);
	m_SkyMgr->Init(mCamera);
	// ------
	// Start Bullet
	m_dispatcher=0;

	///register some softbody collision algorithms on top of the default btDefaultCollisionConfiguration
	m_collisionConfiguration = new btSoftBodyRigidBodyCollisionConfiguration();


	m_dispatcher = new	btCollisionDispatcher(m_collisionConfiguration);
	m_softBodyWorldInfo.m_dispatcher = m_dispatcher;

	btVector3 worldAabbMin(-1000,-1000,-1000);
	btVector3 worldAabbMax(1000,1000,1000);
	m_broadphase = new btAxisSweep3(worldAabbMin,worldAabbMax,32766);

	m_softBodyWorldInfo.m_broadphase = m_broadphase;
	m_solver = new btSequentialImpulseConstraintSolver();


	mWorld = new btSoftRigidDynamicsWorld(m_dispatcher,m_broadphase,m_solver,m_collisionConfiguration);
	///////

// 	btDefaultCollisionConfiguration *collisionConfiguration = new btDefaultCollisionConfiguration();
// 	btCollisionDispatcher *dispatcher = new btCollisionDispatcher(collisionConfiguration);
// 	btBroadphaseInterface *broadphase = new btDbvtBroadphase();
// 	btConstraintSolver *solver = new btSequentialImpulseConstraintSolver();
// 
// 	mWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
	mWorld->setGravity(btVector3(0,-9.81, 0));
	m_softBodyWorldInfo.m_gravity.setValue(0,-9.81,0);
	m_softBodyWorldInfo.m_sparsesdf.Initialize();


	m_BOfactory = new BasicObjFac(mSceneMgr, mWorld);

	//LoadTrack();
	m_Vehicle = NULL;
	LoadCarFile();

	//InitWater();
	m_HydraxOcean = NULL;
	InitWater();

	InitUI();
	//load world
	m_worldLoader = new LoadAllWorld(mSceneMgr, mWorld, NULL, &m_softBodyWorldInfo);
	m_worldLoader->Init("p2scene.scene", NULL);
	mCamera->setPosition(mSceneMgr->getSceneNode("cameraP0")->getPosition());
	mCamera->setOrientation(mSceneMgr->getSceneNode("cameraP0")->getOrientation());

	m_LineManual = new Ogre::ManualObject("btline");
	mSceneMgr->getRootSceneNode()->attachObject(m_LineManual);
	m_LineManual->setDynamic(true);

	SetEffect();
	//init speedboat
	m_speedboat = new Speedboat(mSceneMgr, m_worldLoader->GetObj("dcSBoat"), m_HydraxOcean);
	m_Robot = new RobotCtrl(mSceneMgr, "t_robot");

	m_nv1 = mSceneMgr->getSceneNode("openNV")->getPosition();
	m_nv2 = mSceneMgr->getSceneNode("openNV")->getPosition();
}

bool testBullet::frameRenderingQueued( const Ogre::FrameEvent& evt )
{
	if(!BaseApplication::frameRenderingQueued(evt))
	{
		return false;
	}

	if (mWorld && m_StartPhy)
	{
		mWorld->stepSimulation(evt.timeSinceLastFrame);

		if (m_Vehicle)
		{
			if (m_VehicleRotateState==VEHICLE_LROT)
				m_Vehicle->Control(CAR_TURN_LEFT);
			if (m_VehicleRotateState==VEHICLE_RROT)
				m_Vehicle->Control(CAR_TURN_RIGHT);
			m_Vehicle->Updata();
			Ogre::Vector3 dif = m_nv1 - m_Vehicle->GetSceneNode()->getPosition();
			if (dif.length()<50)
				Ogre::CompositorManager::getSingleton().setCompositorEnabled(
					m_HydraxOcean->getViewport(),"Night Vision",true);
			dif = m_nv2 - m_Vehicle->GetSceneNode()->getPosition();
			if (dif.length()<50)
				Ogre::CompositorManager::getSingleton().setCompositorEnabled(
					m_HydraxOcean->getViewport(),"Night Vision",false);
		}
		ColidEvent();
		if (m_SkyMgr)
			m_SkyMgr->Updata(evt.timeSinceLastFrame);
		m_speedboat->Updata();
		DrawSoftBody();
		m_Robot->Updata(evt.timeSinceLastFrame);
		if (!m_BoatShoot && m_Robot->IsAttack())
		{
			m_speedboat->SetVisiable(true);
			m_speedboat->SetPhyEnable(true);
			Ogre::Vector3 srcpos = mSceneMgr->getSceneNode("movTarget2")->getPosition();
			Ogre::Vector3 trgpos = mSceneMgr->getSceneNode("dcStone1")->getPosition();
			Ogre::Vector3 dif = trgpos - srcpos;
			dif.normalise();
			
			m_speedboat->Shoot(dif * 5000);
			m_BoatShoot = true;
			m_ViewState = CAMERA_BOAT_VIEW;
			Ogre::CompositorManager::getSingleton().setCompositorEnabled(
				m_HydraxOcean->getViewport(),"Radial Blur",true);
			ChangeCameraView();
		}
	}


	if (m_HydraxOcean)
		m_HydraxOcean->update(evt.timeSinceLastFrame);

	m_HikariMgr->update();

	return true;
}

bool testBullet::keyPressed(const OIS::KeyEvent& arg)
{

	if (arg.key == OIS::KC_NUMPAD0)
		m_SkyMgr->setTimeMultiplier(2);
	if (arg.key == OIS::KC_NUMPAD8)
	{
		m_Vehicle->Control(CAR_RUN);
		//m_Vehicle->AddForce(Ogre::Vector3(0,100000,0));
	}
	if (arg.key == OIS::KC_NUMPAD2)
	{
		m_Vehicle->Control(CAR_BACK);
	}

	if (arg.key == OIS::KC_NUMPAD4)
	{
		m_VehicleRotateState = VEHICLE_LROT;
	}
	if (arg.key == OIS::KC_NUMPAD6)
	{
		m_VehicleRotateState = VEHICLE_RROT;
	}

	if (arg.key == OIS::KC_NUMPAD5)
	{
		m_Vehicle->Control(CAR_STOP);
	}

	if (arg.key == OIS::KC_Q)
		m_Vehicle->RotateToUp();

	if (arg.key == OIS::KC_P)
	{
		if (m_ViewState == CAMERA_CAR_VIEW)
			m_ViewState = CAMERA_WORLD_VIEW;
		else
			m_ViewState = CAMERA_CAR_VIEW;
		ChangeCameraView();
	}
	if (arg.key == OIS::KC_O)
		m_StartPhy = !m_StartPhy;

	if (arg.key == OIS::KC_L)
		AddLampStand1(m_Vehicle->GetSceneNode()->getPosition());

	if (arg.key == OIS::KC_S)
		WriteCarFile();
	if (arg.key == OIS::KC_L)
		ReloadCarFile();
	if (arg.key == OIS::KC_C)
		m_speedboat->SetRun(true);
	if (arg.key == OIS::KC_V)
		SaveCubeFile();
	if (arg.key == OIS::KC_B)
		LoadCubeFile();

	if (arg.key == OIS::KC_1)
		m_ObjCtrl->switchMode(ObjectControl::Move_Mode);
	if (arg.key == OIS::KC_2)
		m_ObjCtrl->switchMode(ObjectControl::Rotate_Mode);
	if (arg.key == OIS::KC_3)
		m_ObjCtrl->switchMode(ObjectControl::Scale_Mode);

	if (arg.key == OIS::KC_LMENU || arg.key == OIS::KC_RMENU)
		m_AltKeyPressed = true;

	if (arg.key == OIS::KC_9)
	{
		Ogre::CompositorManager::getSingleton().setCompositorEnabled(m_HydraxOcean->getViewport(),"Night Vision",true);
		Ogre::CompositorManager::getSingleton().setCompositorEnabled(m_HydraxOcean->getViewport(),"Radial Blur",false);
	}

	if (arg.key == OIS::KC_0)
	{
		Ogre::CompositorManager::getSingleton().setCompositorEnabled(m_HydraxOcean->getViewport(),"Night Vision",false);
		Ogre::CompositorManager::getSingleton().setCompositorEnabled(m_HydraxOcean->getViewport(),"Radial Blur",true);
	}

	if (arg.key == OIS::KC_SPACE)
	{
		Ogre::Vector3 movtag = mSceneMgr->getSceneNode("movTarget1")->getPosition();
		Ogre::Vector3 atktag = mSceneMgr->getSceneNode("dcStone1")->getPosition();
		m_Robot->RunAndAttack(movtag, atktag);
	}

	return true;
}

bool testBullet::keyReleased( const OIS::KeyEvent& arg )
{
	if (arg.key == OIS::KC_NUMPAD4)
		m_VehicleRotateState = VEHICLE_NOROT;
	
	if (arg.key == OIS::KC_NUMPAD6)
		m_VehicleRotateState = VEHICLE_NOROT;


	if (arg.key == OIS::KC_LMENU || arg.key == OIS::KC_RMENU)
		m_AltKeyPressed = false;

	return true;
}


bool testBullet::mouseMoved( const OIS::MouseEvent& arg )
{
	if(m_LMouseDown)
		m_ObjCtrl->mouseDragged(arg);

	if (m_AltKeyPressed)
		cameraCtrl(arg);

	BaseApplication::mouseMoved(arg);
	return m_HikariMgr->injectMouseMove(arg.state.X.abs, arg.state.Y.abs) || m_HikariMgr->injectMouseWheel(arg.state.Z.rel);

}

bool testBullet::mousePressed( const OIS::MouseEvent& arg, OIS::MouseButtonID id )
{
	if(id == OIS::MB_Left)
	{
		m_ObjCtrl->mousePressed(arg);
		m_LMouseDown = true;
	}
	else if(id == OIS::MB_Right)	// if the right mouse button is held we hide the mouse cursor for view mode
	{
		m_RMouseDown = true;
	}


	return m_HikariMgr->injectMouseDown(id);
}

bool testBullet::mouseReleased( const OIS::MouseEvent& arg, OIS::MouseButtonID id )
{
	if(id  == OIS::MB_Left)
	{
		m_ObjCtrl->mouseReleased();
		m_LMouseDown = false;
	}
	else if(id == OIS::MB_Right)	//when the right mouse is released we then unhide the cursor
	{
		m_RMouseDown = false;
	}

	return m_HikariMgr->injectMouseUp(id);
}

void testBullet::AddLampStand1( Ogre::Vector3 pos )
{
	OgreNE newNE;
	newNE.node = mSceneMgr->getRootSceneNode()->createChildSceneNode(pos);
	newNE.node->setScale(3.0, 3.0, 3.0);
	newNE.ent = mSceneMgr->createEntity("LampStand1.mesh"); 
	newNE.ent->setQueryFlags(0x01);
	newNE.node->attachObject(newNE.ent);

	Ogre::Light* l = mSceneMgr->createLight();
	l->setType( Ogre::Light::LT_POINT );
	l->setPowerScale(10.0);
	l->setPosition(0.0, 0.3, 0.0);
	l->setCastShadows(true);
	newNE.node->attachObject(l);


	m_vOgreEN.push_back(newNE);
}

void testBullet::ChangeCameraView()
{
	if (m_ViewState == CAMERA_WORLD_VIEW)
	{
		mCamera->detachFromParent();
		mCamera->setPosition(m_OldCameraPos);
		mCamera->setOrientation(m_OldCameraQuat);
	}
	else if (m_ViewState == CAMERA_CAR_VIEW)
	{
		mCamera->detachFromParent();
		if (m_Vehicle)
			m_Vehicle->GetSceneNode()->attachObject(mCamera);
		m_OldCameraPos = mCamera->getPosition();
		m_OldCameraQuat = mCamera->getOrientation();

		mCamera->setPosition(0, 25,-50);
		mCamera->setOrientation(Ogre::Quaternion::IDENTITY);
		mCamera->rotate(Ogre::Vector3(1,0,0), Ogre::Radian(-3.14/9));
		mCamera->rotate(Ogre::Vector3(0,1,0), Ogre::Radian(3.14159));
	}
	else if (m_ViewState == CAMERA_BOAT_VIEW)
	{
		mCamera->detachFromParent();
		Ogre::SceneNode* bnode = m_speedboat->GetBoatSceneNode();
		if (bnode)
			bnode->attachObject(mCamera);
		m_OldCameraPos = mCamera->getPosition();
		m_OldCameraQuat = mCamera->getOrientation();

		mCamera->setPosition(0, 25,-50);
		mCamera->setOrientation(Ogre::Quaternion::IDENTITY);
		mCamera->rotate(Ogre::Vector3(1,0,0), Ogre::Radian(-3.14/9));
		mCamera->rotate(Ogre::Vector3(0,1,0), Ogre::Radian(3.14159));
	}
}

void testBullet::WriteCarFile()
{
	if (!m_Vehicle)
		return;

	const char carfn[] = "../media/setting/CarInf.txt";
	FILE* carf = fopen(carfn, "w");
	if (!carf)
		return;

	float mess = m_Vehicle->GetMess();
	fprintf(carf, "%f ", mess);

	Ogre::Vector3 vpos = m_Vehicle->GetSceneNode()->getPosition();
	fprintf(carf, "%f %f %f ", (float)vpos.x, (float)vpos.y, (float)vpos.z);

	Ogre::Quaternion vq = m_Vehicle->GetSceneNode()->getOrientation();
	fprintf(carf, "%f %f %f %f ", (float)vq.x, (float)vq.y, (float)vq.z, (float)vq.w);

	Ogre::Vector3 vscl = m_Vehicle->GetSceneNode()->getScale();
	fprintf(carf, "%f %f %f ", (float)vscl.x, (float)vscl.y, (float)vscl.z);

	float wheelSize = m_Vehicle->GetWheelSize();
	fprintf(carf, "%f ", wheelSize);

	Ogre::String vmn = m_Vehicle->GetMeshName();
	fprintf(carf, "%s", vmn.c_str());
	fclose(carf);
}

void testBullet::LoadCarFile()
{
	if (m_Vehicle)
		return;
	const char carfn[] = "../media/setting/CarInf.txt";
	FILE* carf = fopen(carfn, "r");
	if (!carf)
		return;

	float mess;
	fscanf(carf, "%f ", &mess);

	Ogre::Vector3 vpos;
	fscanf(carf, "%f %f %f ", &(float)vpos.x, &(float)vpos.y, &(float)vpos.z);

	Ogre::Quaternion vq;
	fscanf(carf, "%f %f %f %f ", &(float)vq.x, &(float)vq.y, &(float)vq.z, &(float)vq.w);

	Ogre::Vector3 vscl;
	fscanf(carf, "%f %f %f ", &(float)vscl.x, &(float)vscl.y, &(float)vscl.z);

	float wheelSize;
	fscanf(carf, "%f ", &wheelSize);

	char meshname[256];
	fscanf(carf, "%s", &meshname);

	m_Vehicle = new Vehicle(mWorld, mSceneMgr, meshname, "wheel.mesh", mess, vpos, 
		vscl, wheelSize, vq);

	fclose(carf);
}

void testBullet::ReloadCarFile()
{
	if (m_Vehicle)
		return;
	const char carfn[] = "../media/setting/CarInf.txt";
	FILE* carf = fopen(carfn, "r");
	if (!carf)
		return;

	float mess;
	fscanf(carf, "%f ", &mess);

	Ogre::Vector3 vpos;
	fscanf(carf, "%f %f %f ", &(float)vpos.x, &(float)vpos.y, &(float)vpos.z);

	Ogre::Quaternion vq;
	fscanf(carf, "%f %f %f %f ", &(float)vq.x, &(float)vq.y, &(float)vq.z, &(float)vq.w);

	Ogre::Vector3 vscl;
	fscanf(carf, "%f %f %f ", &(float)vscl.x, &(float)vscl.y, &(float)vscl.z);

	float wheelSize;
	fscanf(carf, "%f ", &wheelSize);

	char meshname[256];
	fscanf(carf, "%s", &meshname);

	m_Vehicle->TranslateCar(vpos, vq);

	fclose(carf);
}

void testBullet::cameraCtrl(const OIS::MouseEvent& arg)
{
	const OIS::MouseState &ms = mMouse->getMouseState();
	Ogre::Vector3 translateVector(Ogre::Vector3::ZERO);
	Ogre::Degree rotX(0);
	Ogre::Degree rotY(0);
	Ogre::Degree RotationScal = Ogre::Degree(40);
	Ogre::Real MoveScale =10.0;

	if (arg.state.Z.rel > 0)
	{
		Ogre::Vector3 direction = Ogre::Vector3(0,0,-MoveScale);
		mCamera->setPosition(mCamera->getPosition()+mCamera->getOrientation()*direction);

	}
	else if (arg.state.Z.rel < 0)
	{
		Ogre::Vector3 direction = Ogre::Vector3(0,0,MoveScale);
		mCamera->setPosition(mCamera->getPosition()+mCamera->getOrientation()*direction);

	}
	if (ms.buttonDown(OIS::MB_Middle) && m_AltKeyPressed)
	{
		translateVector.x -= ms.X.rel * 0.02f * MoveScale;
		translateVector.y += ms.Y.rel * 0.02f * MoveScale;
	}
	else if (ms.buttonDown(OIS::MB_Left) && m_AltKeyPressed)
	{
		rotX += Ogre::Degree(-ms.X.rel * 0.0025f * RotationScal);
		rotY += Ogre::Degree(-ms.Y.rel * 0.0025f * RotationScal);
	}
	else if (ms.buttonDown(OIS::MB_Right) && m_AltKeyPressed)
	{
		Ogre::Vector3 direction = Ogre::Vector3(0,0,-ms.Y.rel * 0.0025f *MoveScale);
		mCamera->setPosition(mCamera->getPosition()+mCamera->getOrientation()*direction);
	}
	mCamera->setPosition(mCamera->getPosition()+mCamera->getOrientation()*translateVector);
	mCamera->yaw(rotX);
	mCamera->pitch(rotY);

	Ogre::SceneNode* sn = mSceneMgr->getRootSceneNode()->createChildSceneNode();
	sn->setPosition(10,10,10);
	Ogre::SceneNode* sn2 = sn->createChildSceneNode();
	sn2->setPosition(100,0,-100);

}


void testBullet::AddCube()
{
	char cubename[256];
	sprintf(cubename, "XCube%d", m_CubeSet.size());
	EntityWrapper* abox = m_BOfactory->CreateCube(cubename, "cube.mesh", 1.0f, Vector3(0,0,0), Vector3(15,40,5), Quaternion::IDENTITY, 0x1);
	m_CubeSet.push_back(abox);
}

void testBullet::LoadCubeFile()
{
	const char cfn[] = "../media/setting/CubeInfo.txt";
	FILE* cff = fopen(cfn, "r");
	if (!cff)
		return;

	char cubename[256];
	int n;
	fscanf(cff, "%d\n", &n);
	for (int i=0; i<n; i++)
	{
		float mess;
		fscanf(cff, "%f ", &mess);

		Ogre::Vector3 pos;
		fscanf(cff, "%f %f %f ", &(float)pos.x, &(float)pos.y, &(float)pos.z);

		Ogre::Vector3 scl;
		fscanf(cff, "%f %f %f ", &(float)scl.x, &(float)scl.y, &(float)scl.z);

		Ogre::Quaternion q;
		fscanf(cff, "%f %f %f %f\n", &(float)q.x, &(float)q.y, &(float)q.z, &(float)q.w);

		sprintf(cubename, "XCube%d", i+m_CubeSet.size());
		EntityWrapper* abox = m_BOfactory->CreateCube(cubename, "cube.mesh", mess, pos, scl, q, 0x1);
	}

	fclose(cff);
}

void testBullet::SaveCubeFile()
{
	int n = m_CubeSet.size();

	const char cfn[] = "../media/setting/CubeInfo.txt";
	FILE* cff = fopen(cfn, "w");
	if (!cff)
		return;

	fprintf(cff, "%d\n", n);
	for (int i=0; i<n; i++)
	{
		EntityWrapper *cube = m_CubeSet[i];
		float mess = cube->GetMess();
		fprintf(cff, "%f ", mess);

		Ogre::Vector3 pos = cube->getRigidBody()->mNode->getPosition();
		fprintf(cff, "%f %f %f ", (float)pos.x, (float)pos.y, (float)pos.z);

		Ogre::Vector3 scl = cube->getRigidBody()->mNode->getScale();
		fprintf(cff, "%f %f %f ", (float)scl.x, (float)scl.y, (float)scl.z);

		Ogre::Quaternion q = cube->getRigidBody()->mNode->getOrientation();
		fprintf(cff, "%f %f %f %f\n", (float)q.x, (float)q.y, (float)q.z, (float)q.w);
	}

	fclose(cff);
}

void testBullet::ReloadCube()
{
	char cubename[256];
	int n = m_CubeSet.size();
	for (int i=0; i<n; i++)
	{
		EntityWrapper* oldcube = m_CubeSet[i];
		float mess = oldcube->GetMess();
		Ogre::Vector3 pos = oldcube->getRigidBody()->mNode->getPosition();
		Ogre::Vector3 scl = oldcube->getRigidBody()->mNode->getScale();
		Ogre::Quaternion q = oldcube->getRigidBody()->mNode->getOrientation();


		delete oldcube;
		sprintf(cubename, "XCube%d", i);
		EntityWrapper* newcube = m_BOfactory->CreateCube(cubename, "cube.mesh", mess, pos, scl, q, 0x1);
		m_CubeSet[i] = newcube;
	}
}

void testBullet::ResetCube()
{
	int n = m_CubeSet.size();
	for (int i=0; i<n; i++)
	{
		EntityWrapper* oldcube = m_CubeSet[i];
		Ogre::Vector3 pos = oldcube->getRigidBody()->mNode->getPosition();
		Ogre::Quaternion q = oldcube->getRigidBody()->mNode->getOrientation();
		oldcube->ChangePhyState(pos, q);
	}
}

void testBullet::ColidEvent()
{
	Ogre::SceneNode *node1, *node2;

	int numManifolds = mWorld->getDispatcher()->getNumManifolds();

	for(int i=0;i<numManifolds;i++)

	{

		btPersistentManifold * contactManifold = mWorld->getDispatcher()->getManifoldByIndexInternal(i);
		int numContacts= contactManifold->getNumContacts();
		if(numContacts>0)
		{
			btRigidBody* obA = static_cast<btRigidBody*>(contactManifold->getBody0());
			btRigidBody* obB = static_cast<btRigidBody*>(contactManifold->getBody1());
			node1 = (Ogre::SceneNode*)obA->getUserPointer();
			node2 = (Ogre::SceneNode*)obB->getUserPointer();

			if (node1 && node2)
			{
				if (node1->getName()=="scB10" && node2->getName().substr(0, 6)=="dsBall")
				{
					obB->applyForce(btVector3(-sqrt(3.0f)*100, 100, 0), btVector3(0, 0, 0));
				}
				else if(node2->getName()=="scB10" && node1->getName().substr(0, 6)=="dsBall")
				{
					obA->applyForce(btVector3(-sqrt(3.0f)*100, 100, 0), btVector3(0, 0, 0));
				}
				else if (node1->getName()=="dcSwitchZ1" || node2->getName()=="dcSwitchZ1")
				{
					if (!m_speedboat->IsRun())
					{
						m_speedboat->SetRun(true);
						m_ViewState = CAMERA_BOAT_VIEW;
						ChangeCameraView();
					}
				}
				else if (!m_BoatShoot && node1->getName()=="dcSBoat" && node2->getName()=="scAircraft" )
				{
					Ogre::SceneNode* node = mSceneMgr->getSceneNode("movTarget2");
					m_speedboat->SetTransform(node->getPosition(), node->getOrientation());
					m_speedboat->SetVisiable(false);
					m_speedboat->SetPhyEnable(false);

					Ogre::Vector3 movtag = mSceneMgr->getSceneNode("movTarget1")->getPosition();
					Ogre::Vector3 atktag = mSceneMgr->getSceneNode("dcStone1")->getPosition();
					m_Robot->RunAndAttack(movtag, atktag);

					m_OldCameraPos = mSceneMgr->getSceneNode("cameraP1")->getPosition();
					m_OldCameraQuat = mSceneMgr->getSceneNode("cameraP1")->getOrientation();
					m_ViewState = CAMERA_WORLD_VIEW;
					ChangeCameraView();
				}
				else if ((node1->getName()=="dcSBoat" && node2->getName()=="dcStone1")||
					(node2->getName()=="dcSBoat" && node1->getName()=="dcStone1") )
				{
					m_Vehicle->Control(CAR_RUN);
					m_ViewState = CAMERA_CAR_VIEW;
					ChangeCameraView();
					Ogre::CompositorManager::getSingleton().setCompositorEnabled(
						m_HydraxOcean->getViewport(),"Radial Blur",false);
				}
			}
		}

	}
}

void testBullet::DrawSoftBody()
{
	//retrieve the vertex data from the softbody.
	btSoftBody *ogreSoftBody;
	int i=0;
	m_LineManual->clear();
	while(true)
	{
		ogreSoftBody = m_worldLoader->GetSoftbody(i);
		if (!ogreSoftBody)
			return;
		i++;
		btSoftBody::tNodeArray&  nodes(ogreSoftBody->m_nodes);
		int size = nodes.size();
		if (size>20)	//cloth
		{
			size = floor(sqrt(float(size)));
			m_LineManual->begin("NewyearCloth", Ogre::RenderOperation::OperationType::OT_TRIANGLE_LIST);
			for (int j=0; j<size-1;j++)
			{
				for (int k=0; k<size-1; k++)
				{
					int id = j*size+k;	//triangle1
					Ogre::Vector3 p(nodes[id].m_x.x(), nodes[id].m_x.y(), nodes[id].m_x.z());
					m_LineManual->position(p);
					m_LineManual->textureCoord(float(j)/size, float(k)/size);
					id = j*size+k+1;
					p = Ogre::Vector3(nodes[id].m_x.x(), nodes[id].m_x.y(), nodes[id].m_x.z());
					m_LineManual->position(p);
					m_LineManual->textureCoord(float(j)/size, float(k+1)/size);
					id = (j+1)*size+k;
					p = Ogre::Vector3(nodes[id].m_x.x(), nodes[id].m_x.y(), nodes[id].m_x.z());
					m_LineManual->position(p);
					m_LineManual->textureCoord(float(j+1)/size, float(k)/size);

					id = j*size+k+1;	//triangle2
					p = Ogre::Vector3(nodes[id].m_x.x(), nodes[id].m_x.y(), nodes[id].m_x.z());;
					m_LineManual->position(p);
					m_LineManual->textureCoord(float(j)/size, float(k+1)/size);
					id = (j+1)*size+k+1;
					p = Ogre::Vector3(nodes[id].m_x.x(), nodes[id].m_x.y(), nodes[id].m_x.z());
					m_LineManual->position(p);
					m_LineManual->textureCoord(float(j+1)/size, float(k+1)/size);
					id = (j+1)*size+k;
					p = Ogre::Vector3(nodes[id].m_x.x(), nodes[id].m_x.y(), nodes[id].m_x.z());
					m_LineManual->position(p);
					m_LineManual->textureCoord(float(j+1)/size, float(k)/size);
				}
			}
		}
		else			//Line
		{
			m_LineManual->begin("BaseWhiteNoLighting", Ogre::RenderOperation::OperationType::OT_LINE_STRIP);
			for (int j=0;j<nodes.size();j++)
			{
				Ogre::Vector3 p(nodes[j].m_x.x(),
					nodes[j].m_x.y(),
					nodes[j].m_x.z());
				m_LineManual->position(p);
			}
		}
		m_LineManual->end();
	}


}

void testBullet::InitWater()
{
	m_HydraxOcean = new Hydrax::Hydrax(mSceneMgr, mCamera, mWindow->getViewport(0));

	// Create our projected grid module  
	Hydrax::Module::ProjectedGrid *mModule 
		= new Hydrax::Module::ProjectedGrid(// Hydrax parent pointer
		m_HydraxOcean,
		// Noise module
		new Hydrax::Noise::Perlin(/*Generic one*/),
		// Base plane
		Ogre::Plane(Ogre::Vector3(0,1,0), Ogre::Vector3(0,0,0)),
		// Normal mode
		Hydrax::MaterialManager::NM_VERTEX,
		// Projected grid options
		Hydrax::Module::ProjectedGrid::Options(/*264 /*Generic one*/));

	// Set our module
	m_HydraxOcean->setModule(static_cast<Hydrax::Module::Module*>(mModule));

	// Load all parameters from config file
	// Remarks: The config file must be in Hydrax resource group.
	// All parameters can be set/updated directly by code(Like previous versions),
	// but due to the high number of customizable parameters, since 0.4 version, Hydrax allows save/load config files.
	m_HydraxOcean->loadCfg("HydraxDemo.hdx");

	// Create water
	m_HydraxOcean->create();

	// Hydrax initialization code end -----------------------------------------
	// ------------------------------------------------------------------------

	m_HydraxOcean->getMaterialManager()->addDepthTechnique(
		static_cast<Ogre::MaterialPtr>(Ogre::MaterialManager::getSingleton().getByName("Island"))
		->createTechnique());
}

void testBullet::InitUI()
{
	m_HikariMgr = new Hikari::HikariManager("..\\media\\UI");

	m_UIctrl = m_HikariMgr->createFlashOverlay("UIx", m_HydraxOcean->getViewport(), 350, 450, Hikari::Position(Hikari::TopLeft));
	m_UIctrl->load("ui.swf");
	m_UIctrl->setTransparent(true);
	m_UIctrl->setDraggable(false);

	m_UIctrl->bind("btn_start", Hikari::FlashDelegate(this, &testBullet::UIStartPhy));
	m_UIctrl->bind("btn_pause", Hikari::FlashDelegate(this, &testBullet::UIPausePhy));
	m_UIctrl->bind("btn_exit", Hikari::FlashDelegate(this, &testBullet::UIExitPhyS));

	m_UIctrl->bind("btn_freeview", Hikari::FlashDelegate(this, &testBullet::UIChangeToFreeView));
	m_UIctrl->bind("btn_modelview", Hikari::FlashDelegate(this, &testBullet::UIChangeToObjView));

	m_UIctrl->bind("btn_radial_blur", Hikari::FlashDelegate(this, &testBullet::UISetRadialBlur));
	m_UIctrl->bind("chk_night_vision", Hikari::FlashDelegate(this, &testBullet::UISetNightVision));

	m_UIctrl->bind("slider_timespeed", Hikari::FlashDelegate(this, &testBullet::UITimeSpeedSlider));
	m_UIctrl->bind("slider_carspeed", Hikari::FlashDelegate(this, &testBullet::UICarSpeedSlider));
}

void testBullet::SetEffect()
{
	CompositorManager::getSingleton().addCompositor(m_HydraxOcean->getViewport(), "Night Vision");
	Ogre::CompositorManager::getSingleton().setCompositorEnabled(m_HydraxOcean->getViewport(),"Night Vision",false);
	CompositorManager::getSingleton().addCompositor(m_HydraxOcean->getViewport(), "Radial Blur");
	Ogre::CompositorManager::getSingleton().setCompositorEnabled(m_HydraxOcean->getViewport(),"Radial Blur",false);
}

Hikari::FlashValue testBullet::UIStartPhy( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	m_StartPhy = true;
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UIPausePhy( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	m_StartPhy = false;
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UIExitPhyS( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	mShutDown = true;
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UIChangeToFreeView( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UIChangeToObjView( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UISetRadialBlur( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	m_UseRB = !m_UseRB;
	Ogre::CompositorManager::getSingleton().setCompositorEnabled(
		m_HydraxOcean->getViewport(),"Radial Blur",m_UseRB);
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UISetNightVision( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	m_UseNV = !m_UseNV;
	Ogre::CompositorManager::getSingleton().setCompositorEnabled(
		m_HydraxOcean->getViewport(),"Night Vision",m_UseNV);
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UITimeSpeedSlider( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	float i = (float)args.at(0).getNumber()*0.5f;
	m_SkyMgr->setTimeMultiplier(i);
	return FLASH_VOID;
}

Hikari::FlashValue testBullet::UICarSpeedSlider( Hikari::FlashControl* caller, const Hikari::Arguments& args )
{
	float i = (float)args.at(0).getNumber()*0.2f;
	m_Vehicle->SetEngineForceMutlier(i);
	return FLASH_VOID;
}



#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
#define WIN32_LEAN_AND_MEAN
#include "windows.h"
#endif

#ifdef __cplusplus
extern "C" {
#endif

#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
    INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR strCmdLine, INT )
#else
    int main(int argc, char *argv[])
#endif
    {
        // Create application object
        testBullet app;

        try {
            app.go();
        } catch( Ogre::Exception& e ) {
#if OGRE_PLATFORM == OGRE_PLATFORM_WIN32
            MessageBox( NULL, e.getFullDescription().c_str(), "An exception has occured!", MB_OK | MB_ICONERROR | MB_TASKMODAL);
#else
            std::cerr << "An exception has occured: " <<
                e.getFullDescription().c_str() << std::endl;
#endif
        }

        return 0;
    }

#ifdef __cplusplus
}
#endif
